﻿//===========================[ 8 / 8 / 2011 LVI ]=============================
//				Copyright c Vitaly Lyaschenko <SkyChameleon@gmail.com>
//								Source file
// Purpose: 
//=============================================================================
#include "cCamera.h"
#include "windows.h"
#include "cTimer.h"

const float PI3 = PI / 3;

cCamera::cCamera(void) :
    m_ViewMtr( mat4_identity ),
    m_ProjectionMtr( mat4_identity ),
    m_EyePos( vec3_zero ),
    m_Rotation( vec3_zero )
{
    pMous = Kernel::spec().getMous();
    pMous->attach(Kernel::spec().getHWND());

    speed = 20;
    m_Rotation.y = 45;
}

cCamera::~cCamera(void)
{
    pMous->detach();
}

void cCamera::setPerspective( const float aspectRatio/* ,float fov,float zNear, float zFar,const char* type*/ )
{
    perspective( m_ProjectionMtr, 45.0f, aspectRatio, 0.1f, 1000.0f );
}

void cCamera::setLookAt( const vec3 &position, const vec3 &center, const vec3 &up )
{
    m_Rotation = toEuler( lookAt( position, m_viewDir = center, m_Up = up ) );
    m_EyePos = position;
}

///////////////////////////////////////////////////////////////////////////
//  получение матрицы вращения из углов эйлера
mat4 cCamera::getRotationMtr()
{
    return fromEuler( m_Rotation );
}
///////////////////////////////////////////////////////////////////////////
// матрица проэкции
mat4 & cCamera::getMtrProjection()
{
    return m_ProjectionMtr;
}
///////////////////////////////////////////////////////////////////////////
// матрица вида
mat4 & cCamera::getMtrView()
{
    return m_ViewMtr;
}

void cCamera::moveUp( float dist )
{
    m_EyePos += transpose(getRotationMtr()) * vec3( 0, dist, 0 );
}

void cCamera::moveForward( float dist )
{
    m_EyePos +=  transpose(getRotationMtr()) * vec3( 0, 0, -dist );
}

void cCamera::moveForwardOnGround( float dist )
{
    vec3 v = transpose(getRotationMtr()) * vec3( 0, 0, -1 );
    v.y = 0;
    normalize( v );
    m_EyePos += v * dist;
}

void cCamera::moveSide( float dist )
{
    m_EyePos += transpose(getRotationMtr()) * vec3( dist, 0, 0 );
}

void cCamera::update( float deltaTime )
{
    m_Rotation.x = 0;
    m_Rotation.y = 0;
    
    Pitch( pMous->getXpos() * 0.1f );
    Yaw( pMous->getYpos() * 0.1f );

    if ( GetKeyState(VK_LSHIFT) & 0x80 || GetKeyState(VK_RSHIFT) & 0x80 )
    {               
        multiplier = 2;
    }
    if ( GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80 )
    {               
        moveForward( -speed * deltaTime * multiplier );	             
    }

    if ( GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80 )
    {         
        moveForward( speed * deltaTime * multiplier );
    }

    if ( GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80 )
    {         
        moveSide( speed * deltaTime * multiplier );
    }

    if ( GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80 ) 
    {
        moveSide( -speed * deltaTime * multiplier );
    }

    if ( GetKeyState(VK_TAB) & 0x80 || GetKeyState('Q') & 0x80 )
    {               
        setPosition( vec3(-20, 0, -20) );
    }

    multiplier = 1;

    m_ViewMtr = getRotationMtr() * translation( m_EyePos );
}